//
//  KDDCollection.m
//  MengLiao
//
//  Created by xiuxin on 2022/7/15.
//  Copyright © 2022 HZMengLiao. All rights reserved.
//

#import "KDDCollection.h"
#import "KDDStorage.h"
#import "KDDModel.h"
#import "KDDConfigStore.h"
#import "KDDCollectionLayout.h"
#import <objc/runtime.h>


@interface UICollectionReusableView (KDataDriven)

@property (copy,nonatomic) dispatch_block_t kDDConfigBlock;

@end

@implementation UICollectionReusableView (KDataDriven)

- (dispatch_block_t)kDDConfigBlock
{
    return objc_getAssociatedObject(self, @selector(kDDConfigBlock));
}

- (void)setKDDConfigBlock:(dispatch_block_t)block
{
    objc_setAssociatedObject(self, @selector(kDDConfigBlock), block, OBJC_ASSOCIATION_COPY);
}

@end

@implementation UICollectionView (KDataDriven)

- (id<KDataDriven>)kDataDriven
{
    KDDCollection * ddCollection = objc_getAssociatedObject(self, _cmd);
    if (!ddCollection)
    {
        ddCollection = [KDDCollection new];
        [ddCollection applyToLayoutView:self];
        self.kDataDriven = ddCollection;
    }
    return ddCollection;
}

- (void)setKDataDriven:(id<KDataDriven>)kDataDriven
{
    objc_setAssociatedObject(self, @selector(kDataDriven), kDataDriven, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (id<KDataDrivenConfigure>)kConfigure
{
    return self.kDataDriven.configure;
}

- (id<KDataDrivenStorage>)kStorage
{
    return self.kDataDriven.storage;
}

@end

@interface KDDCollectionLayout (KDDCollection)

- (void)willCommitUpdate:(KDDUpdate *)updateList data:(NSArray<KDDSectionData *> *)data;

- (void)didCommitUpdate:(KDDUpdate *)updateList data:(NSArray<KDDSectionData *> *)data;

- (void)checkAndUpdateLayout;

@end

@interface KDDCollection() <UICollectionViewDelegate,UICollectionViewDataSource,KDDUpdateHandler>

@property (weak,nonatomic) UICollectionView * collectionView;

@property (weak,nonatomic) KDDCollectionLayout * collectionViewLayout;

@property (weak,nonatomic) id outDelegate;

@property (strong,nonatomic) KDDConfigure * configure;

@property (strong,nonatomic) KDDStorage * storage;

@end

@implementation KDDCollection
@dynamic additionalDelegate;

- (instancetype)initWithStorage:(id<KDataDrivenStorage>)storage
{
    if (self = [super init])
    {
        _configure = [[KDDConfigure alloc] init];
        _storage = storage ?: [KDDStorage new];
        _storage.updateHandler = self;
    }
    return self;
}

- (instancetype)init
{
    return [self initWithStorage:[KDDStorage new]];
}

- (void)useSharedConfigure
{
    _configure.configStore = [KDDConfigStore sharedStore];
    if (self.collectionView != nil)
    {
        [_configure applyToLayoutView:self.collectionView];
    }
}

- (__kindof UIView *)layoutView
{
    return _collectionView;
}

- (id<KDataDrivenStorage>)storage
{
    return _storage;
}

- (NSArray<KDDPosition *> *)visiblePositionList
{
    NSMutableArray<KDDPosition *> * positionList = [NSMutableArray array];
    for (NSIndexPath * indexPath in [self.collectionView indexPathsForVisibleItems])
    {
        [positionList addObject:[KDDPosition cellPosition:indexPath]];
    }
    if (@available(iOS 9.0, *))
    {
        for (NSIndexPath * indexPath in [self.collectionView indexPathsForVisibleSupplementaryElementsOfKind:UICollectionElementKindSectionHeader])
        {
            [positionList addObject:[KDDPosition headerPosition:indexPath.section]];
        }
        for (NSIndexPath * indexPath in [self.collectionView indexPathsForVisibleSupplementaryElementsOfKind:UICollectionElementKindSectionFooter])
        {
            [positionList addObject:[KDDPosition footerPosition:indexPath.section]];
        }
    }
    else if (positionList.count > 0)
    {
        NSArray<KDDPosition *> * sortedPositionList = [KDDPosition sortedPositionList:positionList];
        KDDPosition * minPosition = sortedPositionList.firstObject;
        KDDPosition * maxPosition = sortedPositionList.lastObject;
        for (NSInteger section = minPosition.section; section <= maxPosition.section; section++)
        {
            KDDSectionData * sectionData = kObjectFromArray(self.storage.data,section);
            if (sectionData.headerModel != nil)
            {
                [positionList addObject:[KDDPosition headerPosition:section]];
            }
            if (sectionData.footerModel != nil)
            {
                [positionList addObject:[KDDPosition footerPosition:section]];
            }
        }
    }
    return positionList;
}

- (__kindof UIView *)wrapperViewAtPosition:(KDDPosition *)position
{
    if (position.viewType == KDDViewTypeCell)
    {
        return [self.collectionView cellForItemAtIndexPath:position.indexPath];
    }
    else if (@available(iOS 9.0, *))
    {
        if (position.viewType == KDDViewTypeHeader)
        {
            return [self.collectionView supplementaryViewForElementKind:UICollectionElementKindSectionHeader atIndexPath:position.indexPath];
        }
        else if (position.viewType == KDDViewTypeFooter)
        {
            return [self.collectionView supplementaryViewForElementKind:UICollectionElementKindSectionFooter atIndexPath:position.indexPath];
        }
        else if (position.viewType == KDDViewTypeDecoration)
        {
            KDDDecorationModel * decorationModel = [self.collectionViewLayout decorationModelAtPosition:position];
            UIView * wrapperView = [self.collectionView supplementaryViewForElementKind:decorationModel.reuseID atIndexPath:position.indexPath];
            return wrapperView ?: decorationModel.decorationView;
        }
    }
    return nil;
}

- (void)selectItemAtPosition:(KDDPosition *)position animated:(BOOL)animated scrollPosition:(KDDScrollPosition)scrollPosition offsetY:(CGFloat) offsetY {
    CGRect frame = [self rectForItemAtPosition:position];
    UIEdgeInsets displayInsets = [self.collectionViewLayout displayInsets];
    if (scrollPosition == KDDScrollPositionTop)
    {
        CGFloat headerHeight = 0;
        if (position.viewType == KDDViewTypeCell)
        {
            KDDPosition * headerPosition = [self.collectionViewLayout headerPositionForItemAtPosition:position];
            if (headerPosition != nil)
            {
                headerHeight = [self sizeForItemAtIndexPath:headerPosition.indexPath viewType:KDDViewTypeHeader].height;
            }
        }
        [self.collectionView setContentOffset:CGPointMake(0, frame.origin.y - displayInsets.top - headerHeight + offsetY) animated:animated];
    }
    else if (scrollPosition == KDDScrollPositionMiddle)
    {
        [self.collectionView setContentOffset:CGPointMake(0, CGRectGetMidY(frame) - displayInsets.top - (self.collectionView.bounds.size.height - displayInsets.top - displayInsets.bottom) / 2.0f + offsetY) animated:animated];
    }
    else if (scrollPosition == KDDScrollPositionBottom)
    {
        CGFloat footerHeight = 0;
        if (position.viewType == KDDViewTypeCell)
        {
            KDDPosition * footerPosition = [self.collectionViewLayout footerPositionForItemAtPosition:position];
            if (footerPosition != nil)
            {
                footerHeight = [self sizeForItemAtIndexPath:footerPosition.indexPath viewType:KDDViewTypeFooter].height;
            }
        }
        [self.collectionView setContentOffset:CGPointMake(0, CGRectGetMaxY(frame) - self.collectionView.bounds.size.height + displayInsets.bottom + footerHeight + offsetY) animated:animated];
    }
}

- (void)selectItemAtPosition:(KDDPosition *)position animated:(BOOL)animated scrollPosition:(KDDScrollPosition)scrollPosition
{
    [self selectItemAtPosition:position animated:animated scrollPosition:scrollPosition offsetY:0];
}

- (CGRect)rectForItemAtPosition:(KDDPosition *)position
{
    return [self.collectionViewLayout rectForPosition:position];
}

- (NSInteger)numberOfSections
{
    return self.storage.data.count;
}

#pragma mark Configure

- (void)applyToLayoutView:(UICollectionView *)collectionView
{
    if (@available(iOS 10.0, *))
    {
        collectionView.prefetchingEnabled = NO;
    }
    self.collectionView = collectionView;
    self.collectionViewLayout = (KDDCollectionLayout *)collectionView.collectionViewLayout;
    collectionView.kDataDriven = self;
    collectionView.delegate = self;
    collectionView.dataSource = self;
    [self.configure applyToLayoutView:collectionView];
}

- (void)setAdditionalDelegate:(id)additionalDelegate
{
    _outDelegate = additionalDelegate;
    _collectionView.delegate = nil;
    _collectionView.delegate = self;
}

- (id)additionalDelegate
{
    return _outDelegate;
}

#pragma mark UICollectionView Delegate DataSource

- (void)handleEvent:(KDDEventType)event viewType:(KDDViewType)viewType indexPath:(NSIndexPath *)indexPath wapperView:(UICollectionReusableView *)wapperView
{
    KDDPosition * position = [KDDPosition positionWithViewType:viewType indexPath:indexPath];
    NSObject * model = [self.storage modelAtPosition:position];
    KDDConfig * config = [self.configure modelConfigWithID:model.ddConfigID];
    KExecuteBlock([config handlerForEvent:event], wapperView, model, position);
}

- (void)willDisplayWrapperView:(UICollectionReusableView *)wrapperView viewType:(KDDViewType)viewType indexPath:(NSIndexPath *)indexPath
{
    if ([wrapperView respondsToSelector:@selector(ddWillDisplay:position:)])
    {
        KDDPosition * position = [KDDPosition positionWithViewType:viewType indexPath:indexPath];
        NSObject * model = [self.storage modelAtPosition:position];
        [(UIView<KDDReuseView> *)wrapperView ddWillDisplay:model position:position];
    }
    else
    {
        [self handleEvent:KDDWillDisplayEvent viewType:viewType indexPath:indexPath wapperView:wrapperView];
    }
    KExecuteBlock(wrapperView.kDDConfigBlock);
}

- (void)endDisplayWrapperView:(UICollectionReusableView *)wrapperView viewType:(KDDViewType)viewType indexPath:(NSIndexPath *)indexPath
{
    if ([wrapperView respondsToSelector:@selector(ddEndDisplay:position:)])
    {
        KDDPosition * position = [KDDPosition positionWithViewType:viewType indexPath:indexPath];
        NSObject * model = [self.storage modelAtPosition:position];
        [(UIView<KDDReuseView> *)wrapperView ddEndDisplay:model position:position];
    }
    else
    {
        [self handleEvent:KDDEndDisplayEvent viewType:viewType indexPath:indexPath wapperView:wrapperView];
    }
}

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
    [self handleEvent:KDDSelectModelEvent viewType:KDDViewTypeCell indexPath:indexPath wapperView:nil];
}

- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath
{
    [self willDisplayWrapperView:cell viewType:KDDViewTypeCell indexPath:indexPath];
}

- (void)collectionView:(UICollectionView *)collectionView willDisplaySupplementaryView:(UICollectionReusableView *)view forElementKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath
{
    KDDViewType viewType = KDDViewTypeNone;
    if ([elementKind isEqualToString:UICollectionElementKindSectionHeader])
    {
        viewType = KDDViewTypeHeader;
    }
    else if ([elementKind isEqualToString:UICollectionElementKindSectionFooter])
    {
        viewType = KDDViewTypeFooter;
    }
    [self willDisplayWrapperView:view viewType:viewType indexPath:indexPath];
}

- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath
{
    [self endDisplayWrapperView:cell viewType:KDDViewTypeCell indexPath:indexPath];
}

- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingSupplementaryView:(UICollectionReusableView *)view forElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath
{
    KDDViewType viewType = KDDViewTypeNone;
    if ([elementKind isEqualToString:UICollectionElementKindSectionHeader])
    {
        viewType = KDDViewTypeHeader;
    }
    else if ([elementKind isEqualToString:UICollectionElementKindSectionFooter])
    {
        viewType = KDDViewTypeFooter;
    }
    [self endDisplayWrapperView:view viewType:viewType indexPath:indexPath];
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    if (section < self.storage.data.count)
    {
        return self.storage.data[section].cellModelList.count;
    }
    return 0;
}

- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView wrapperViewForItemAtIndexPath:(NSIndexPath *)indexPath viewType:(KDDViewType)viewType
{
    KDDPosition * position = [KDDPosition positionWithViewType:viewType indexPath:indexPath];
    NSObject * model = [self.storage modelAtPosition:position];
    UICollectionReusableView * wrapperView = nil;
    KDDConfig * config = [self.configure modelConfigWithID:model.ddConfigID];
    if (model.ddReuseID.length == 0)
    {
        if (config.reuseIDBlock != nil)
        {
            model.ddReuseID = config.reuseIDBlock(model, viewType);
        }
        if (model.ddReuseID == nil)
        {
            model.ddReuseID = config.reuseID;
        }
    }
    if ([self.configure registerInfoForReuseID:model.ddReuseID viewType:viewType] == nil)
    {
        Class wrapperClass = config.wrapperClassBlock(model.ddReuseID, viewType);
        KDDRegisterInfo * info = [[KDDRegisterInfo alloc] initWithViewType:viewType wrapperClass:wrapperClass reuseID:model.ddReuseID];
        [self.configure addRegisterInfo:info];
        config.registerInfo[model.ddReuseID] = info;
    }
    if (viewType == KDDViewTypeCell)
    {
        wrapperView = [collectionView dequeueReusableCellWithReuseIdentifier:model.ddReuseID forIndexPath:indexPath];
    }
    else if (viewType == KDDViewTypeHeader)
    {
        wrapperView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:model.ddReuseID forIndexPath:indexPath];
    }
    else if (viewType == KDDViewTypeFooter)
    {
        wrapperView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:model.ddReuseID forIndexPath:indexPath];
    }
    NSValue * sizeValue = model.ddSize;
    if (sizeValue == nil)
    {
        if ([wrapperView.class respondsToSelector:@selector(sizeForModel:position:)])
        {
            CGSize size = [(id<KDDReuseView>)wrapperView.class sizeForModel:model position:position];
            sizeValue = [NSValue valueWithCGSize:size];
        }
        else if (config.sizeBlock != nil)
        {
            sizeValue = config.sizeBlock(model, position);
        }
        if (sizeValue == nil)
        {
            sizeValue = config.itemSize;
        }
    }
    if (sizeValue == nil || CGSizeEqualToSize(sizeValue.CGSizeValue, [self backAuotomaticSize]))
    {
        wrapperView.kDDConfigBlock = nil;
        if ([wrapperView respondsToSelector:@selector(ddLoadModel:position:)])
        {
            [(UIView<KDDReuseView> *)wrapperView ddLoadModel:model position:position];
        }
        else
        {
            KExecuteBlock([config handlerForEvent:KDDLoadModelEvent], wrapperView, model, position);
        }
    }
    else
    {
        __weak UICollectionReusableView * wView = wrapperView;
        if ([wrapperView respondsToSelector:@selector(ddLoadModel:position:)])
        {
            wrapperView.kDDConfigBlock = ^{
                __strong UICollectionReusableView * sView = wView;
                [(UIView<KDDReuseView> *)sView ddLoadModel:model position:position];
            };
        }
        else
        {
            KDDEventHandler handler = [config handlerForEvent:KDDLoadModelEvent];
            if (handler != nil)
            {
                wrapperView.kDDConfigBlock = ^{
                    __strong UICollectionReusableView * sView = wView;
                    handler(sView, model, position);
                };
            }
        }
    }
    return wrapperView;
}
- (CGSize)backAuotomaticSize
{
    if (@available(iOS 10.0, *)) {
        return UICollectionViewFlowLayoutAutomaticSize;
    }
    return CGSizeZero;
}
// The cell that is returned must be retrieved from a call to -dequeueReusableCellWithReuseIdentifier:forIndexPath:
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    return (UICollectionViewCell *)[self collectionView:collectionView wrapperViewForItemAtIndexPath:indexPath viewType:KDDViewTypeCell];
}

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
    return self.storage.data.count;
}

// The view that is returned must be retrieved from a call to -dequeueReusableSupplementaryViewOfKind:withReuseIdentifier:forIndexPath:
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
    if ([kind isEqualToString:UICollectionElementKindSectionHeader])
    {
        if ([self.storage modelAtPosition:[KDDPosition headerPosition:indexPath.section]] != nil)
        {
            return (UICollectionReusableView *)[self collectionView:collectionView wrapperViewForItemAtIndexPath:indexPath viewType:KDDViewTypeHeader];
        }
    }
    else if ([kind isEqualToString:UICollectionElementKindSectionFooter])
    {
        if ([self.storage modelAtPosition:[KDDPosition footerPosition:indexPath.section]] != nil)
        {
            return (UICollectionReusableView *)[self collectionView:collectionView wrapperViewForItemAtIndexPath:indexPath viewType:KDDViewTypeFooter];
        }
    }
    return nil;//忽略静态检查
}

/// Returns a list of index titles to display in the index view (e.g. ["A", "B", "C" ... "Z", "#"])
- (nullable NSArray<NSString *> *)indexTitlesForCollectionView:(UICollectionView *)collectionView API_AVAILABLE(tvos(10.2))
{
    if (self.enableIndexTitles)
    {
        NSMutableArray<NSString *> * indexTitles = [NSMutableArray arrayWithCapacity:self.storage.data.count];
        for (KDDSectionData * sectionData in self.storage.data)
        {
            [indexTitles addObject:sectionData.indexTitle ?: @""];
        }
        return indexTitles;
    }
    return nil;
}

/// Returns the index path that corresponds to the given title / index. (e.g. "B",1)
/// Return an index path with a single index to indicate an entire section, instead of a specific item.
- (NSIndexPath *)collectionView:(UICollectionView *)collectionView indexPathForIndexTitle:(NSString *)title atIndex:(NSInteger)index API_AVAILABLE(tvos(10.2))
{
    for (KDDSectionData * sectionData in self.storage.data)
    {
        [title isEqualToString:sectionData.indexTitle ?: @""];
        return [NSIndexPath indexPathForRow:0 inSection:sectionData.index];
    }
    return nil; //忽略静态检查
}

- (CGSize)sizeForItemAtIndexPath:(NSIndexPath *)indexPath viewType:(KDDViewType)viewType
{
    KDDPosition * position = [KDDPosition positionWithViewType:viewType indexPath:indexPath];
    NSObject * model = [self.storage modelAtPosition:position];
    if (model == nil)
    {
        return CGSizeZero;
    }
    NSValue * sizeValue = model.ddSize;
    if (sizeValue == nil)
    {
        KDDConfig * config = [self.configure modelConfigWithID:model.ddConfigID];
        if (config.sizeBlock != nil)
        {
            sizeValue = config.sizeBlock(model, position);
        }
        if (sizeValue == nil)
        {
            sizeValue = config.itemSize;
        }
    }
    return sizeValue == nil ? [self backAuotomaticSize] : [sizeValue CGSizeValue];
}

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
    return [self sizeForItemAtIndexPath:indexPath viewType:KDDViewTypeCell];
}

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section
{
    return [self sizeForItemAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:section] viewType:KDDViewTypeHeader];
}

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section
{
        return [self sizeForItemAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:section] viewType:KDDViewTypeFooter];
}

- (CGPoint)collectionView:(UICollectionView *)collectionView targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset
{
    return proposedContentOffset;
}

#pragma mark FlowLayout Inset

- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
    if (section < self.storage.data.count)
    {
        return self.storage.data[section].sectionInsets;
    }
    return UIEdgeInsetsZero;
}

- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section
{
    if (section < self.storage.data.count)
    {
        return self.storage.data[section].minimumLineSpacing;
    }
    return 0;
}

- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section
{
    if (section < self.storage.data.count)
    {
        return self.storage.data[section].minimumInteritemSpacing;
    }
    return 0;
}

#pragma mark KDDUpdateHandler

- (void)dataStorage:(id<KDataDrivenStorage>)storage willCommitUpdate:(KDDUpdate *)update
{
    //更新操作前强制获取数据源个数
    NSInteger sectionCount = [self.collectionView numberOfSections];
    if (update.target == KDDTargetSection)
    {
        [update.indexSet enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull stop) {
            if (idx < sectionCount)
            {
                [self.collectionView numberOfItemsInSection:idx];
            }
        }];
    }
    else if (update.target == KDDTargetCell)
    {
        KOSUpdate * osUpdate = (KOSUpdate *)update;
        for (KDDUpdate * object in osUpdate.updateList)
        {
            if (object.section < sectionCount)
            {
                [self.collectionView numberOfItemsInSection:object.section];
            }
        }
    }
    [self.collectionViewLayout willCommitUpdate:update data:self.storage.data];
//    NSLog(@"willCommitUpdate:%ld",self.collectionView.numberOfSections);
}

- (void)dataStorage:(id<KDataDrivenStorage>)storage didCommitUpdate:(KDDUpdate *)update
{
//    NSLog(@"didCommitUpdate numberOfSections:%ld",self.collectionView.numberOfSections);
    [self.collectionViewLayout didCommitUpdate:update data:self.storage.data];
    
    if (update.target == KDDTargetList)
    {
        [self.collectionView reloadData];
    }
    else if (update.target == KDDTargetSection)
    {
        if (update.updateType == KDDUpdateInsert)
        {
            [self.collectionView insertSections:update.indexSet];
        }
        else if (update.updateType == KDDUpdateDelete)
        {
            [self.collectionView deleteSections:update.indexSet];
        }
        else
        {
            [UIView performWithoutAnimation:^{
                [self.collectionView reloadSections:update.indexSet];
            }];
        }
    }
    else if ([update isKindOfClass:[KOSUpdate class]])
    {
        KOSUpdate * osUpdate = (KOSUpdate *)update;
        if (osUpdate.target == KDDTargetCell)
        {
            NSMutableArray<NSIndexPath *> * indexPathList = [NSMutableArray arrayWithCapacity:osUpdate.positionList.count];
            for (KDDPosition * position in osUpdate.positionList)
            {
                [indexPathList addObject:position.indexPath];
            }
            if (osUpdate.updateType == KDDUpdateInsert)
            {
                [self.collectionView insertItemsAtIndexPaths:indexPathList];
            }
            else if (update.updateType == KDDUpdateDelete)
            {
                [self.collectionView deleteItemsAtIndexPaths:indexPathList];
            }
            else
            {
                [self.collectionView reloadItemsAtIndexPaths:indexPathList];
            }
        }
    }
//    NSLog(@"didCommitUpdate Over");
    [self.collectionViewLayout checkAndUpdateLayout];
}

- (void)dataStorage:(id<KDataDrivenStorage>)storage performBatchUpdates:(void (^)(void))updates completion:(void (^)(BOOL finished))completion
{
    updates();
    KExecuteBlock(completion,YES);
//    [self.collectionView performBatchUpdates:^{
////        [self.collectionViewLayout willBeginBatchUpdate];
//        updates();
////        [self.collectionViewLayout didEndBatchUpdate];
//    } completion:^(BOOL finished) {
////        [self.collectionViewLayout checkAndUpdateLayout];
//        KExecuteBlock(completion,finished);
//    }];
}

#pragma mark 代理消息转发
- (BOOL)respondsToSelector:(SEL)aSelector
{
    return [super respondsToSelector:aSelector] || [_outDelegate respondsToSelector:aSelector];
}

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
    if ([_outDelegate respondsToSelector:anInvocation.selector])
    {
        [anInvocation invokeWithTarget:_outDelegate];
    }
    else if ([super respondsToSelector:anInvocation.selector])
    {
        [super forwardInvocation:anInvocation];
    }
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
    NSMethodSignature * sig = nil;
    if ((sig = [_outDelegate methodSignatureForSelector:aSelector]))
    {
        return sig;
    }
    return [super methodSignatureForSelector:aSelector];
}

@end

